package com.zhy.generator.codegen.mybatis.javaconstant;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zhy.generator.codegen.api.CommentGenerator;
import com.zhy.generator.codegen.api.IntrospectedColumn;
import com.zhy.generator.codegen.dom.java.*;
import com.zhy.generator.codegen.mybatis.AbstractJavaGenerator;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

import static com.zhy.generator.codegen.util.JavaBeansUtil.getJavaBeansGetter;
import static com.zhy.generator.codegen.util.Messages.getString;

/**
 * @author 源
 */
public class JavaConstantGenerator extends AbstractJavaGenerator {
    @Override
    public List<CompilationUnit> getCompilationUnits() {
        progressCallback.startTask(getString("Progress.16", introspectedTable.getFullyQualifiedTable()));
        CommentGenerator commentGenerator = context.getCommentGenerator();

        FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getConsTantType());
        TopLevelClass tlc = new TopLevelClass(type);
        tlc.setVisibility(JavaVisibility.PUBLIC);
        commentGenerator.addJavaFileComment(tlc);

        List<IntrospectedColumn> allColumns = introspectedTable.getAllColumns();
        for (IntrospectedColumn column : allColumns) {
            String remarks = column.getRemarks();
            if (remarks.startsWith("constant")) {
                tlc.addImportedType("com.google.common.collect.Maps");
                tlc.addImportedType(PrimitiveTypeWrapper.getNewMapInstance());

                JSONObject jsonObject = parserJsonRemark(column.getRemarks());

                Method getAllMethod = createGetAllDescMethod(column);
                tlc.addMethod(getAllMethod);
                Method getDesc = createGetDescMethod(column, getAllMethod);
                tlc.addMethod(getDesc);

                createConstantFields(column, tlc, getAllMethod, getDesc, jsonObject);
            }
        }

        List<CompilationUnit> answer = new ArrayList<CompilationUnit>();
        List<Field> fields = tlc.getFields();
        if (CollectionUtils.isEmpty(fields)) {
            return answer;
        }
        answer.add(tlc);

        return answer;
    }

    private JSONObject parserJsonRemark(String remarks) {
        remarks = remarks.replace("constant", "");
        return JSONUtil.parseObj(remarks);
    }

    private Method createGetAllDescMethod(IntrospectedColumn column) {
        Method getAllMethod = new Method();
        getAllMethod.setVisibility(JavaVisibility.PUBLIC);
        getAllMethod.setStatic(true);
        Method getterMethod = getJavaBeansGetter(column, context, introspectedTable);
        getAllMethod.setName(getterMethod.getName() + "s");
        return getAllMethod;
    }

    private Method createGetDescMethod(IntrospectedColumn column, Method getAllMethod) {

        Method getDesc = new Method();
        getDesc.setVisibility(JavaVisibility.PUBLIC);
        getDesc.setStatic(true);
        getDesc.setReturnType(PrimitiveTypeWrapper.getStringInstance());
        Method getterMethod = getJavaBeansGetter(column, context, introspectedTable);
        getDesc.setName(getterMethod.getName());
        getDesc.addBodyLine("return " + getAllMethod.getName() + "().get(" + column.getJavaProperty() + ");");
        return getDesc;
    }

    private void createConstantFields(IntrospectedColumn column, TopLevelClass tlc, Method getAllMethod, Method getDesc, JSONObject jsonObject) {
//        constant{"type":"integer","desc":"是否删除","name":"deleted","values":[{"value":"0","remark":"否"},{"value":"1","remark":"是"}]}

        String fieldType = jsonObject.getStr("type");
        FullyQualifiedJavaType fullFieldtype = PrimitiveTypeWrapper.getIntegerInstance();
        if ("string".equals(fieldType)) {
            fullFieldtype = FullyQualifiedJavaType.getStringInstance();
        }
        tlc.addImportedType(fullFieldtype);

        Parameter p = new Parameter(fullFieldtype, column.getJavaProperty());
        getDesc.addParameter(p);

        FullyQualifiedJavaType mapType = PrimitiveTypeWrapper.getNewMapInstance();
        mapType.addTypeArgument(fullFieldtype);
        mapType.addTypeArgument(PrimitiveTypeWrapper.getStringInstance());

        getAllMethod.setReturnType(mapType);
        getAllMethod.addBodyLine("Map<" + fullFieldtype.getShortName() + ", String> datas = Maps.newHashMap();");


        String desc = jsonObject.getStr("desc");
        String name = jsonObject.getStr("name");
        JSONArray values = jsonObject.getJSONArray("values");

        for (Object value : values) {
            JSONObject valueObject = JSONUtil.parseObj(String.valueOf(value));
            String v = valueObject.getStr("value");
            String remark = valueObject.getStr("remark");
            Field field = createField(fullFieldtype, v, name, remark, desc);
            tlc.addField(field);
            getAllMethod.addBodyLine("datas.put(" + field.getName() + ",\"" + remark + "\");");
        }
        getAllMethod.addBodyLine("return datas;");

    }

    public Field createField(FullyQualifiedJavaType fullFieldtype, String value, String name, String remark, String desc) {
        Field field = new Field();
        field.setFinal(true);
        field.setVisibility(JavaVisibility.PUBLIC);
        field.setStatic(true);
        field.setType(fullFieldtype);
        field.setInitializationString(value);
        field.setName(name.toUpperCase() + "_" + value.toUpperCase());
        field.addJavaDocLine("//" + desc + "_" + remark);

        return field;
    }
}
